package owg.util.opengl.models;

import owg.util.opengl.EGL;
import owg.util.opengl.GLRenderable;
import owg.util.euclidian.VXD;
import owg.util.euclidian.VXF;


/**
 * Abstract high performance renderable. Can either be a Vertex Buffer Object, a Vertex Array or a Display List.
 * The construction functions do not perform any OpenGL calls until end() is called.
 * Subinterfaces must specify which data type to use for vertex data.
 * */
public abstract interface HPRI extends GLRenderable
	{
	/**Can be used to set the index data instead of adding indices/faces, when building the HPR.*/
	public abstract void setPrepackedIData(int[] data);
	
	/**Set an upper limit for how many vertices to render, -1 for no limit.
	 * It is never necessary to call requestIUpdate after this call. 
	 * All implementations support changing the render limit without rebuffering any data, with the exception of display lists.
	 * For this reason, you should avoid calling this on display list-based implementations.*/
	public abstract void setRenderLimit(int limit);
	
	/**Can be used to specify explicitly when the current sequence should end, and what the next sequence's mode should be.
	 * Note that the last sequence is automatically ended after the last index when end() is called.
	 * Also note that the first sequence is automatically started when the object is created.*/
	public abstract void addSequence(int terminatingIndex, int newFaceMode);
	
	/**Makes a triangle from the last three vertices.*/
	public abstract void triangle(boolean reverse);

	/**Add 3 indices. Use to make faces from vertices.*/
	public abstract void triangle(int i1, int i2, int i3);

	/**Add two triangles from the last 4 vertices. If faceMode is GL_TRIANGLES, 6 indices are added.*/
	public abstract void quad(boolean reverse);

	/**Add 6 indices from 4 inputs as if it was a trianglestrip, or 4 indices if the mode is currently triangle_strip.*/
	public abstract void quad(int i1, int i2, int i3, int i4);

	/**Add an index. Use to make faces from vertices.*/
	public abstract void addIndex(int index);

	/**Get the current size of the vertex list*/
	public abstract int getIndex();

	/**Call after changing the vertex array. Update mode should be dynamic if this is called often.
	 * The VBO, display list or directbuffer gets updated on the next render call.*/
	public abstract void requestVUpdate();

	/**Terminate the current sequence and begin a new one with the indicated face mode*/
	public abstract void addSequence(int newFaceMode);

	/**Complete the HPR from the data input*/
	public abstract void end(EGL<?> egl);
	
	/**Returns the list of indices used for the index buffer object. Note that these are vertex indices, 
	 * so if they are used for lookup in the vertex array then they need to be multiplied by {@link #getVStride()}.<br>
	 * Useful for saving model data, etc.*/
	public abstract int[] getIData();
	
	/**Changes to this array are not supported, but it is useful for saving model data, etc.*/
	public abstract int[] getFaceModeEndIndices();
	
	/**Changes to this array are not supported, but it is useful for saving model data, etc.*/
	public abstract int[] getFaceModes();
	
	/**Render*/
	public abstract void render();

	/**Free memory.
	 * @param gl The EGL associated with the context where this was created. 
	 * This parameter is a reminder that the context must be current on the thread when calling this.
	 */
	public abstract void dispose(EGL<?> egl);

	/**Inefficient debug method.*/
	public abstract void render(VXD center, double scale);

	/**Inefficient debug method 2.*/
	public abstract void render(VXD center, double xScale, double yScale, double zScale);
	
	/**Inefficient debug method 3.*/
	public abstract void render(VXF center, float scale);

	/**Inefficient debug method 4.*/
	public abstract void render(VXF center, float xScale, float yScale, float zScale);
	
	/**Get the number of indices(floats) occupied by a full vertex in the float array*/
	public abstract int getVStride();
	
	/**Get the index of the vertex position data relative to the start of the nearest full vertex in the float array*/
	public abstract int getVertexPointer();

	/**Get the index of the normal data relative to the start of the nearest full vertex in the float array*/
	public abstract int getNormalPointer();
	
	/**Get the index of the color data relative to the start of the nearest full vertex in the float array*/
	public abstract int getColorPointer();

	/**Get the index of the texture coordinate data relative to the start of the nearest full vertex in the float array*/
	public abstract int getTexCoordPointer();
	
	/**Get the HPR's name*/
	public abstract String getName();

	}